home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
301-325
/
disk_315
/
surf
/
readilbm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-06
|
9KB
|
398 lines
#include <stdio.h>
#include <ctype.h>
#include "readilbm.h"
#define FALSE 0
#define TRUE 1
#define RED 0
#define GRN 1
#define BLU 2
/* color to grey conversion methods */
#define AVERAGE 0
#define LUMIN 1
#define DIST 2
#define REDONLY 3
#define GREENONLY 4
#define BLUEONLY 5
#define MakeID(a,b,c,d) ( ((a)<<24) | ((b)<<16) | ((c)<<8) | (d) )
#define ID_FORM MakeID('F','O','R','M')
#define ID_ILBM MakeID('I','L','B','M')
#define ID_BMHD MakeID('B','M','H','D')
#define ID_CMAP MakeID('C','M','A','P')
#define ID_CAMG MakeID('C','A','M','G')
#define ID_BODY MakeID('B','O','D','Y')
#define ROUNDUP(x) ( ((x)+1) & (~1L) )
static struct CHUNK {
unsigned long Id, Size;
} Chunk;
static unsigned char cmap[32][3];
struct BMHD {
short w,h,x,y;
char npl,mask,compress,pad1;
short transparentColor;
char xAspect,yAspect;
short pageWidth,pageHeight;
};
static short Color[32], /* output colors */
Method = AVERAGE; /* color conversion */
static short numcolors;
static
FILE *fin; /* input file */
extern char *malloc();
static void FRead();
static void ReadBMHD();
static void ReadChunk();
static void RastOut();
static void HamOut();
static char GetIlbmVal();
static void InitColorMappings();
static short Convert();
static void ReadDecomLine();
static void ProcessRows();
#define ABORT(str) { OutErr(str); goto ErrorExit; }
void SetGreyModel( model )
int model;
{
Method = model;
}
/*
* main routine for reading in an iff file
*/
void ReadIlbm(filename)
char *filename;
{
struct BMHD bmhd;
long ILBMid;
unsigned char cmapFlag = FALSE,
bmhdFlag = FALSE;
if ((fin = fopen (filename, "r")) == NULL) {
OutErr ("ERROR: cannot open input file");
return;
}
/* read in iff file */
ReadChunk ();
if (Chunk.Id != ID_FORM)
ABORT ("Not an IFF File");
FRead (&ILBMid, 4);
if (ILBMid != ID_ILBM)
ABORT ("Not an ILBM File");
while (1) {
long camgdata;
ReadChunk ();
if (Chunk.Id == ID_BODY)
break;
if( feof( fin ) ) {
ABORT("reached end of file without seeing body\n");
}
switch (Chunk.Id) {
case ID_CMAP:
FRead (cmap, Chunk.Size);
numcolors = Chunk.Size/3;
cmapFlag = TRUE;
break;
case ID_BMHD:
ReadBMHD (&bmhd);
bmhdFlag = TRUE;
break;
case ID_CAMG:
FRead( &camgdata, sizeof(camgdata) );
break;
default: /* unknown identifier */
fseek( fin, Chunk.Size, 1);
break;
}
}
if (!cmapFlag) {
ABORT("IFF file does not contain a CMAP chunk before the BODY\n");
}
if (!bmhdFlag) {
ABORT("IFF file does not contain a BMHD chunk before the BODY\n");
}
InitColorMappings();
if( OpenImgPix( bmhd.w, bmhd.h, Convert(0xf, 0xf, 0xf)) ) {
ProcessRows(&bmhd);
}
ErrorExit:
fclose( fin);
}
static void ProcessRows(bmhd)
struct BMHD *bmhd;
{
char *rastlist[6];
char *Raster;
int depth, i, v, pixwidth;
int BytePerLine;
depth = bmhd->npl;
pixwidth = bmhd->w;
BytePerLine =(pixwidth+7) / 8;
Raster = (char *) malloc (BytePerLine * depth);
if(!Raster ) {
OutErr("ProcessRows:could not allocate Raster");
return;
}
for( i = 0; i < depth; i++ ) {
rastlist[i] = Raster + BytePerLine*i;
}
for( v = 0; v < bmhd->h; v++) {
switch (bmhd->compress) {
case 0:
FRead (Raster, BytePerLine * depth);
break;
case 1:
for( i = 0; i < depth; i++) {
ReadDecomLine( BytePerLine, rastlist[i]);
}
break;
default:
ABORT ("Unknown Compression type in BODY");
}
if(depth == 6 ) {
HamOut( rastlist, pixwidth, v);
}
else {
RastOut( rastlist, pixwidth, v, depth);
}
}
ErrorExit:
if( Raster ) free(Raster);
}
static void ReadDecomLine(linebytes, rp)
int linebytes;
char *rp;
{
int runlen;
char pixel;
while (linebytes) {
runlen = getc (fin);
if (runlen > 127)
runlen -= 256;
if (runlen >= 0) {
runlen++;
FRead (rp, runlen);
rp += runlen;
linebytes -= runlen;
}
else {
runlen = -runlen + 1;
linebytes -= runlen;
pixel = getc (fin);
do
*(rp++) = pixel;
while (--runlen);
}
}
}
/*
* Convert - convert (r,g,b) to hex greyscale.
*/
static short Convert(r,g,b)
unsigned char r,g,b;
{
short i,
rd, gd, bd,
min,
dist,
best;
/* convert color according to 'Method' */
switch (Method) {
case AVERAGE: /* average r,g,b to obtain grey level */
return ((short)((r + g + b) / 3));
case LUMIN: /* use NTSC luminescence as grey level */
return ((short)((r * 30 + g * 59 + b * 11) / 100));
case DIST: /* use grey with minimum distance in color */
min = 15*15 * 3;
for( i = 0; i < numcolors; i++ ) {
rd = r -i;
gd = g - i;
bd = b - i;
dist = rd * rd + gd * gd + bd * bd;
if( dist < min ) {
min = dist; best = i;
}
}
return( best );
case REDONLY:
return((short)r);
case GREENONLY:
return((short)g);
case BLUEONLY:
return((short)b);
default:
exit(-1); /* error, big one */
}
} /* Convert */
static void InitColorMappings()
{
int i;
/* put colors in 4-bit range and Convert */
for (i = 0; i < 32; i++) {
cmap[i][RED] >>= 4;
cmap[i][GRN] >>= 4;
cmap[i][BLU] >>= 4;
Color[i] = Convert (cmap[i][RED], cmap[i][GRN], cmap[i][BLU]);
}
}
/*
* leftmost pixel of byte is in most significant bit of byte
*/
static char GetIlbmVal( rastlist, h, bpp )
char *rastlist[6];
int h, bpp;
{
int i;
char value = 0;
short mask, bytep;
mask = 0x80 >> ( h & 7);
bytep = h >> 3;
for( i = bpp-1; i >= 0; i-- ) {
value <<= 1;
value |= (*(rastlist[i]+bytep) & mask) ? 1: 0;
}
return( value );
}
/*
* HamOut - output ham image in hex.
*/
static void HamOut(rastlist, pixwidth, v)
char *rastlist[6];
int pixwidth, v;
{
unsigned char lastred = 0,
lastgreen = 0,
lastblue = 0;
int h;
char pixval;
for( h = 0; h <pixwidth; h++ ) {
short shade;
shade = GetIlbmVal(rastlist, h, 6);
pixval = shade & 0x0F;
switch (shade & 0x30) {
case 0x00:
lastred = cmap[pixval][RED];
lastgreen = cmap[pixval][GRN];
lastblue = cmap[pixval][BLU];
shade = Color[pixval];
break;
case 0x10:
lastblue = pixval;
shade = Convert(lastred,lastgreen,lastblue);
break;
case 0x20:
lastred = pixval;
shade = Convert(lastred,lastgreen,lastblue);
break;
case 0x30:
lastgreen = pixval;
shade = Convert(lastred,lastgreen,lastblue);
}
SetImgPix(h, v, shade);
}
}
/*
* RastOut - handle normal bit mapped images
*/
static void RastOut(rastlist, pixwidth, v, depth)
char *rastlist[6];
int pixwidth, v, depth;
{
int h;
for( h = 0; h < pixwidth; h++ ) {
short shade;
shade = Color[GetIlbmVal( rastlist, h, depth)];
SetImgPix( h, v, shade);
}
}
/*
* ReadChunk - read in an IFF Chunk.
*/
static void ReadChunk()
{
FRead (&Chunk, sizeof (Chunk));
} /* ReadChunk */
/*
* ReadBMHD - read the BMHD structure.
*/
static void ReadBMHD(bmhd)
struct BMHD *bmhd;
{
FRead (bmhd, Chunk.Size);
} /* ReadBMHD */
/*
* FRead - read 'len' bytes to 'pointer' while checking for an error.
*/
static void FRead(pointer,len)
char *pointer;
int len;
{
if (fread (pointer, len, 1, fin) == 0) {
char outbuff[90];
sprintf(outbuff,"Fread Error in reading input file at %d ", ftell(fin));
OutErr(outbuff);
}
} /* FRead */